package com.qf.rpc.client;

import com.qf.rpc.SerializeUtil;
import com.qf.rpc.ZkUtil;
import com.qf.rpc.protocol.Request;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.net.Socket;
import java.net.UnknownHostException;

public class ServiceProxy {
    private static ZkUtil util = new ZkUtil();
static {
    util.createConnection();
}
    //代理各个service
    public static Object getProxyInstance(Class clazz) {
        return Proxy.newProxyInstance(clazz.getClassLoader(), new Class<?>[]{clazz}, new InvocationHandler() {
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                //封装请求对象
                Request request = new Request();
                request.setServiceName(clazz.getName());//调用这个类
                request.setMethodName(method.getName());//调用类的这个方法
                request.setParamTypes(method.getParameterTypes());//区分重载方法
                request.setArgs(args);//调用方法时传递的参数
                Socket socket = null;// 1.建立一个与服务端之间的连接
                OutputStream output = null;// 用于向别人发消息
                InputStream input = null;// 用于读取别人发过来的消息
                try {
                    //用硬编码的形式，把服务提供者给写在这了，
                    //如果用注册中心zookeeper,应该在这，通过serviceName去zookeeper查询ip和端口

                    byte[] data = util.getNodeData("/"+request.getServiceName(), false, null);
                    if (data == null) {//没有服务提供者
                        return null;
                    }
                    String ipAddr = new String(data);
                    System.out.println(ipAddr);
                    String[]ipAndPort=ipAddr.split(":");
                    socket = new Socket(ipAndPort[0], Integer.valueOf(ipAndPort[1]));
                    // 2.将需要发送的数据写入到网络中，注意：包含了两个流：InputStream和OutputStream
                    output = socket.getOutputStream();//客户端对服务端说
                    output.write(SerializeUtil.serialize(request));// 3.写入
                    output.flush();
                    // 4.收取服务端发送来的消息 new BufferedInputStream(socket.getInputStream());
                    input = socket.getInputStream();//读服务端的响应
                    byte[] arr = new byte[1024];
                    int len = input.read(arr);
                    Object result = SerializeUtil.unserialize(arr);//服务端的返回结果反序列化
                    return result;
                } catch (UnknownHostException e) {
                    e.printStackTrace();
                } catch (IOException e) {
                    e.printStackTrace();
                } finally {
                    try {
                        input.close();
                        output.close();
                        socket.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
                return null;
            }
        });
    }
}
